using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

using Deepcode.Flux.Core.Data;
using Deepcode.Flux.Core.Services.Security;
using Deepcode.Flux.Core.Systems.Audit;

namespace Deepcode.Flux.Core.Systems.Security
{
	/// <summary>
	/// Manager class for the administration groups table
	/// </summary>
	public class AdministrationGroups : Deepcode.Flux.Core.Data.BaseManager
	{
		#region Constructors
		public AdministrationGroups() : base() { }
		public AdministrationGroups(SqlConnection CurrentConnection) : base(CurrentConnection) { }
		public AdministrationGroups(SqlConnection CurrentConnection, SqlTransaction CurrentTransaction) : base(CurrentConnection, CurrentTransaction) { }
		#endregion
		#region Data Retrieval Methods
		/// <summary>
		/// Gets all of the known administration groups on the system
		/// </summary>
		/// <returns></returns>
		public AdministrationGroup[] GetAllGroups()
		{
			List<AdministrationGroup> results = new List<AdministrationGroup>();
			DataTable result = new DataTable();

			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAdminGroupsGetAll");
			da.Fill(result);
			ReleaseConnection();

			foreach (DataRow r in result.Rows)
				results.Add(new AdministrationGroup(r));

			return results.ToArray();
		}
		/// <summary>
		/// Gets the specific administration group record by it's ID
		/// </summary>
		/// <param name="GroupID"></param>
		/// <returns></returns>
		public AdministrationGroup GetGroupByID(int GroupID)
		{
			DataTable result = new DataTable();
			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAdminGroupsGetByID");
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@id", SqlDbType.Int, 4, GroupID));
			da.Fill(result);
			ReleaseConnection();

			if (result == null) return null;
			if (result.Rows.Count < 1) return null;

			return new AdministrationGroup(result.Rows[0]);
		}
		/// <summary>
		/// Gets the administration groups associated with a particular user.
		/// </summary>
		/// <param name="UserID"></param>
		/// <returns></returns>
		public AdministrationGroup[] GetGroupsForUser(int UserID)
		{
			List<AdministrationGroup> results = new List<AdministrationGroup>();
			DataTable result = new DataTable();

			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAdminGroupsGetForUser");
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@userid", SqlDbType.Int, 4, UserID));
			da.Fill(result);
			ReleaseConnection();

			foreach (DataRow r in result.Rows)
				results.Add(new AdministrationGroup(r));

			return results.ToArray();
		}
		#endregion
		#region Record Save/Delete
		/// <summary>
		/// Saves the administration group record to the database
		/// </summary>
		/// <param name="group"></param>
		/// <returns></returns>
		public int Save(AdministrationGroup group)
		{
			EstablishConnection();
			SqlCommand cmd = this.CreateSqlCommand("coreAdminGroupsSave");
			SqlParameter result = SQLUtility.ParameterInOut("@id", SqlDbType.Int, 4, group.PK_ID);
			cmd.Parameters.Add(result);
			cmd.Parameters.Add(SQLUtility.ParameterIn("@groupname", SqlDbType.NVarChar, 200, group.GroupName));
			cmd.ExecuteNonQuery();
			ReleaseConnection();

			if (group.PK_ID == -1)
				group.PK_ID = (int)result.Value;

			return group.PK_ID;
		}
		/// <summary>
		/// Deletes the specified group from the database
		/// </summary>
		/// <param name="GroupID"></param>
		public void DeleteByID(int GroupID)
		{
			EstablishConnection();		
			SqlCommand cmd = this.CreateSqlCommand("coreAdminGroupsDeleteByID");
			cmd.Parameters.Add(SQLUtility.ParameterIn("@groupid", SqlDbType.Int, 4, GroupID));
			cmd.ExecuteNonQuery();
			ReleaseConnection();
		}
		#endregion
		#region Association Managers
		/// <summary>
		/// Sets the permissions associated with the group. Pass in the
		/// group ID to associate permissions with an an array of strings 
		/// representing permission codes to grant to the group.
		/// </summary>
		/// <param name="GroupID"></param>
		/// <param name="permissionCodes"></param>
		public void SetPermissions(int GroupID, string[] permissionCodes)
		{
			try
			{
				EstablishConnection();
				BeginTransaction();
				// Clear down current permissions
				SqlCommand clearCmd = this.CreateSqlCommand("coreAdminGroupsClearPermissions");
				clearCmd.Parameters.Add(SQLUtility.ParameterIn("@groupid", SqlDbType.Int, 4, GroupID));
				clearCmd.ExecuteNonQuery();
				// Add each of the permissions specified
				foreach (string code in permissionCodes)
				{
					SqlCommand AddCmd = this.CreateSqlCommand("coreAdminGroupsGrantPermission");
					AddCmd.Parameters.Add(SQLUtility.ParameterIn("@groupid", SqlDbType.Int, 4, GroupID));
					AddCmd.Parameters.Add(SQLUtility.ParameterIn("@pcode", SqlDbType.NVarChar, 200, code));
					AddCmd.ExecuteNonQuery();
				}

				EndTransaction(EndTransactionMode.COMMIT);
				ReleaseConnection();
				return;
			}
			catch (Exception e)
			{
				try { EndTransaction(EndTransactionMode.ROLLBACK); }
				catch { }
				try { ReleaseConnection(); }
				catch { }
				throw e;
			}
		}
		#endregion
	}
}
